package com.graphite.task;

import com.graphite.client.GraphiteNettyClientTask;
import com.graphite.model.BaseRequest;
import com.graphite.model.BaseResponse;
import com.graphite.model.GraphiteMetric;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @projectName: graphite-connector-java
 * @packageName: com.graphite.task
 * @className: com.graphite.task-> FetchGraphiteDataTask
 * @createDate: 2021-06-06 19:21
 * @author: ZhangSheng
 * @version: 1.0
 * @description: 操作Graphit数据的执行器
 */
public class FetchGraphiteDataTaskExector<K extends BaseRequest, V extends BaseResponse> {
    private final Logger logger = LoggerFactory.getLogger(FetchGraphiteDataTaskExector.class);
    private ThreadPoolExecutor executor;
    private int corePoolSize;
    private int maximumPoolSize;
    private long keepAliveTime;
    private TimeUnit unit;
    private BlockingQueue<Runnable> workQueue;

    public FetchGraphiteDataTaskExector(){
        this.corePoolSize = 4;
        this.maximumPoolSize = 16;
        this.keepAliveTime = 5000L;
        this.unit = TimeUnit.SECONDS;
        this.workQueue = new ArrayBlockingQueue<Runnable>(16);
        this.executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue);
    }

    /**
     * 向graphite写入数据
     * @param graphiteMetrics 写入的数据集
     * @return
     */
    public Boolean submit(String host, int port,List<GraphiteMetric> graphiteMetrics) throws InterruptedException, ExecutionException, TimeoutException {
        GraphiteNettyClientTask task = new GraphiteNettyClientTask()
                .setHost(host).setPort(port)
                .setGraphiteMetric(graphiteMetrics);
        Future<Boolean> future = this.executor.submit(task);
        return future.get(4,TimeUnit.MINUTES);
    }

    /**
     * 单条请求任务
     * @param request
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public V submit(K request) throws ExecutionException, InterruptedException {
        FetchGraphiteRequestTask<K,V>  task = new FetchGraphiteRequestTask<K, V>(request);
        Future<V> future = executor.submit(task);
        return future.get();
    }

    /**
     * 多条请求任务，多个指标值的获取数据
     * @param requests
     * @return
     */
    public List<V> submit(List<K> requests) throws ExecutionException, InterruptedException {
        if (null==requests || requests.size()<=0){
            return null;
        }
        List<V> resultList = new ArrayList<V>();
        List<Callable<V>> tasks = new ArrayList<Callable<V>>(requests.size());
        for (int i = 0; i < requests.size(); i++) {
            FetchGraphiteRequestTask<K,V>  task = new FetchGraphiteRequestTask<K, V>(requests.get(i));
            tasks.add(task);
        }
        List<Future<V>> futureList = executor.invokeAll(tasks, 10, TimeUnit.MINUTES);
        for (int i = 0; i < futureList.size(); i++) {
            V v = futureList.get(i).get();
            resultList.add(v);
        }
        return resultList;
    }

}
